package com.example.simple_android.annotation.impl;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;

import com.example.simple_android.Manager.impl.BroadcastReceiverManager;
import com.example.simple_android.annotation.Action;
import com.example.simple_android.annotation.Receiver;
import com.example.simple_android.constant.Constant;
import com.example.simple_android.utils.ReflectionsUtil;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class ReceiverImpl {

    /**
     * 广播接收者模板，用于将非标准广播接收者，增强为标准广播接收者
     */
    public static class BroadcastReceiverTemplate extends BroadcastReceiver {

        /**
         * 非标准广播接收者的对象，用于后面通过反射触发onReceive的实现方法
         */
        private Object object;

        /**
         * 标准广播接收者的实现方法，在onReceive触发时，将被通过反射调用
         */
        private Method receiver;

        @Override
        public void onReceive(Context context, Intent intent) {
            receiver.setAccessible(true);
            try {
                receiver.invoke(object, context, intent);
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 调用此方法，在全局注册广播接收者
     *
     * @param context 上下文对象
     */
    public static void initReceiver(Context context) {
        Set<Class<?>> classByAnnotationClass = ReflectionsUtil.getClassByAnnotationClass(Receiver.class);
        if (classByAnnotationClass == null) {
            return;
        }
        for (Class<?> cls : classByAnnotationClass) {
            Receiver receiver = cls.getDeclaredAnnotation(Receiver.class);
            int i = receiver.whenToStart();
            if (i == Constant.ReceiverConstant.WAIT) {
                continue;
            }
            String[] actions = receiver.actions();
            if (actions.length <= 0) {
                continue;
            }
            if (receiver.whenToStart() != Constant.ReceiverConstant.IMMEDIATELY) {
                continue;
            }
            IntentFilter intentFilter = new IntentFilter();
            for (String action : actions) {
                intentFilter.addAction(action);
            }
            try {
                Object instance = cls.newInstance();
                if (instance instanceof BroadcastReceiver) {
                    context.registerReceiver((BroadcastReceiver) instance, intentFilter);

                    BroadcastReceiverManager broadcastReceiverManager = BroadcastReceiverManager.getInstance();
                    Map<String, BroadcastReceiver> map = broadcastReceiverManager.getMap(context);
                    if (map == null) {
                        map = new HashMap<>();
                        broadcastReceiverManager.register(context, map);
                    }
                    map.put(cls.getName(), (BroadcastReceiver) instance);
                } else {
                    initNonStandardReceiver(context, instance, intentFilter, receiver);
                }
            } catch (IllegalAccessException | InstantiationException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 调用此方法，在指定对象中寻找Receiver，并且注册
     *
     * @param context 上下文对象
     * @param o       被寻找Receiver的对象
     * @return 所有被注册的BroadcastReceiver集合
     */
    public static Set<BroadcastReceiver> initFieldReceiver(Context context, Object o) {
        Class<?> aClass = o.getClass();
        Field[] declaredFields = aClass.getDeclaredFields();
        Set<BroadcastReceiver> broadcastReceivers = new HashSet<>();
        for (Field field : declaredFields) {
            try {
                field.setAccessible(true);
                Object obj = field.get(o);
                if (obj == null) {
                    continue;
                }
                if (!(obj instanceof BroadcastReceiver)) {
                    continue;
                }
                Receiver receiver = field.getDeclaredAnnotation(Receiver.class);
                IntentFilter intentFilter = new IntentFilter();
                for (String ac : receiver.actions()) {
                    intentFilter.addAction(ac);
                }
                context.registerReceiver((BroadcastReceiver) obj, intentFilter);
                broadcastReceivers.add((BroadcastReceiver) obj);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        Method[] methods = aClass.getDeclaredMethods();
        for (Method method : methods) {
            Receiver receiver = method.getDeclaredAnnotation(Receiver.class);
            if (receiver == null) {
                continue;
            }
            String[] actions = receiver.actions();
            if (actions.length <= 0) {
                continue;
            }
            BroadcastReceiverTemplate broadcastReceiverTemplate = new BroadcastReceiverTemplate();
            broadcastReceiverTemplate.object = o;
            broadcastReceiverTemplate.receiver = method;
            IntentFilter intentFilter = new IntentFilter();
            for (String action : actions) {
                intentFilter.addAction(action);
            }
            context.registerReceiver(broadcastReceiverTemplate, intentFilter);
            broadcastReceivers.add(broadcastReceiverTemplate);
        }
        return broadcastReceivers.isEmpty() ? null : broadcastReceivers;
    }

    /**
     * 调用此方法，注册指定类中的内部BroadcastReceiver实现类
     *
     * @param context 上下文对象
     * @param o       被寻找内部类的对象
     * @return 被注册的BroadcastReceiver集合
     */
    public static Set<BroadcastReceiver> initInnerClassReceiver(Context context, Object o) {
        Class<?> aClass = o.getClass();
        Class<?>[] declaredClasses = aClass.getDeclaredClasses();
        if (declaredClasses.length <= 0) {
            return null;
        }
        Set<BroadcastReceiver> broadcastReceivers = new HashSet<>();
        for (Class<?> cls : declaredClasses) {
            Receiver receiver = cls.getDeclaredAnnotation(Receiver.class);
            if (receiver == null) {
                continue;
            }
            String[] actions = receiver.actions();
            if (actions.length <= 0) {
                continue;
            }
            if (Constant.ReceiverConstant.FOLLOW_EXTERNAL_CLASS != receiver.whenToStart()) {
                continue;
            }
            try {
                Object instance = cls.newInstance();
                IntentFilter intentFilter = new IntentFilter();
                for (String action : actions) {
                    intentFilter.addAction(action);
                }
                if (instance instanceof BroadcastReceiver) {
                    context.registerReceiver((BroadcastReceiver) instance, intentFilter);
                    broadcastReceivers.add((BroadcastReceiver) instance);
                } else {
                    String methodName = receiver.methodName();
                    if (methodName == null) {
                        continue;
                    }
                    Method method = cls.getDeclaredMethod(methodName, Intent.class);
                    BroadcastReceiverTemplate broadcastReceiverTemplate = new BroadcastReceiverTemplate();
                    broadcastReceiverTemplate.receiver = method;
                    broadcastReceiverTemplate.object = instance;
                    context.registerReceiver(broadcastReceiverTemplate, intentFilter);
                    broadcastReceivers.add(broadcastReceiverTemplate);
                }
            } catch (IllegalAccessException | InstantiationException | NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
        return broadcastReceivers;
    }

    /**
     * 注册非标准BroadcastReceiver
     *
     * @param context      上下文对象
     * @param o            被增强的非标准BroadcastReceiver类
     * @param intentFilter 意图过滤者
     * @param receiver     Receiver注解对象，它携带者被增强的非标准BroadcastReceiver的增强以及注册信息
     */
    private static void initNonStandardReceiver(Context context, Object o, IntentFilter intentFilter, Receiver receiver) {
        Class<?> aClass = o.getClass();
        try {
            Method method = aClass.getDeclaredMethod(receiver.methodName(), Context.class, Intent.class);
            BroadcastReceiverTemplate broadcastReceiverTemplate = new BroadcastReceiverTemplate();
            broadcastReceiverTemplate.receiver = method;
            broadcastReceiverTemplate.object = o;
            context.registerReceiver(broadcastReceiverTemplate, intentFilter);
            BroadcastReceiverManager broadcastReceiverManager = BroadcastReceiverManager.getInstance();
            Map<String, BroadcastReceiver> map = broadcastReceiverManager.getMap(context);
            if (map == null) {
                map = new HashMap<>();
                broadcastReceiverManager.register(context, map);
            }
            map.put(aClass.getName(), broadcastReceiverTemplate);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}
